<?php
/**
 * 扩展后台管理页面
 * @author 楚羽幽 <Name_Cyu@Foxmail.com>
 */
namespace Admin\Controller;
class PlugsController extends AuthController
{
    private $db;
    /**
     * [_initialize 构造函数]
     * @return [type] [description]
     */
    public function _initialize()
    {
        parent::_initialize();

        //删除插件缓存
        S('hooks',null);

        $this->db = D('Plugs');
        $this->assign('field',array('install'=> '已安装插件', 'Addons' => $this->db->getAdminList()));
    }



    /**
     * [index 插件列表]
     * @return [type] [description]
     */
    public function index()
    {
        // 获取所有插件
        $list = $this->db->getAddonList();

        // 获取已安装插件
        $data = $this->db->getAdminList();

        // 分配数据
        $this->assign('install', $data);
        $this->assign('data', $list);
        $this->display();
    }


    /**
     * [create 创建插件]
     * @return [type] [description]
     */
    public function create()
    {
        if (IS_POST)
        {
            // 数据处理开始
            if($this->db->create())
            {
                // 获取数据
                $data = $_POST;
                // 插件名首字母大小
                $data['name']   =   ucfirst($data['name']);
                // 插件代码预览
                $addonFile      =   $this->preview(false);
                // 插件目录路径
                $addons_dir     =   UNION_ADDON_PATH;

                // 验证插件标识
                if($this->PlugsCheck($data['name']))
                {
                    $this->error('操作错误，该插件已经存在！', U('index'));
                    continue;
                }

                // 创建目录结构
                $files          =   array();
                $addon_dir      =   "$addons_dir{$data['name']}/";
                $files[]        =   $addon_dir;
                $addon_name     =   "{$data['name']}Addon.class.php";
                $files[]        =   "{$addon_dir}{$addon_name}";

                // 开启外部访问，创建模型与控制器目录及文件
                if($data['has_outurl'])
                {
                    $files[]    =   "{$addon_dir}Controller/";
                    $files[]    =   "{$addon_dir}Controller/{$data['name']}Controller.class.php";
                    $files[]    =   "{$addon_dir}Model/";
                    $files[]    =   "{$addon_dir}Model/{$data['name']}Model.class.php";
                }

                // 使用函数创建目录及文件
                create_dir_or_files($files);

                //-------------------配置项文件----------------------
                if ($data['config'] == 1)
                {
                    copy(MODULE_PATH . 'Data/Addon/configAddon.php', $addon_dir . 'config.php');
                }

                // 写文件
                file_put_contents("{$addon_dir}{$addon_name}", $addonFile);
                if($data['has_outurl'])
                {
                    $addonController = <<<str
<?php
/**
 * 「PHP联盟」
 * {$data['name']} 控制器
 * {$data['author']} <{$data['email']}>
 */
namespace Plugs\\{$data['name']}\Controller;
use Home\Controller\AddonsController;
class {$data['name']}Controller extends AddonsController
{
    // 方法
}
str;
                file_put_contents("{$addon_dir}Controller/{$data['name']}Controller.class.php", $addonController);
                $addonModel = <<<str
<?php
/**
 * 「PHP联盟」
 * {$data['name']} 模型
 * {$data['author']} <{$data['email']}>
 */
namespace Plugs\\{$data['name']}\Model;
use Think\Model;
class {$data['name']}Model extends Model
{
    // 方法
}
str;
                file_put_contents("{$addon_dir}Model/{$data['name']}Model.class.php", $addonModel);
            }
            $this->success('恭喜，插件创建成功！',U('index'));

            // 数据处理结束
            }
            else
            {
                $this->error($this->db->getError());
            }         
        }
        else
        {
            $this->assign('Hooks', M('Hooks')->select());
            $this->display();
        }
    }





    /**
     * [install 安装插件]
     * @return [type] [description]
     */
    public function install()
    {
        $addon_name = trim(I('addon_name'));
        $class = get_addon_class($addon_name);

        // 插件是否存在
        if (!class_exists($class))
            $this->error('插件不存在', U('index'));

        // 定义类
        $addons = new $class;
        $info = $addons->info;
        if (!$info || !$addons->checkInfo()) //检测信息的正确性
            $this->error('插件信息缺失');
        session('addons_install_error', null);

        $install_flag = $addons->install();
        if (!$install_flag)
        {
            $this->error('执行插件预安装操作失败' . session('addons_install_error'), U('index'));
        }

        $data = $this->db->create($info);
        if (is_array($addons->admin_list) && $addons->admin_list !== array())
        {
            $data['has_adminlist'] = 1;
        }
        else
        {
            $data['has_adminlist'] = 0;
        }
        if (!$data)
            $this->error($this->db->getError());
        if ($this->db->add($data))
        {
            $config = array('config' => json_encode($addons->getConfig()));
            if($this->db->where(array('name'=> $addon_name))->save($config))
            {
                $this->success('插件安装成功！', U('index'));
            }
            else
            {
                $this->error('插件安装失败！', U('index'));
            }
        }
        else
        {
            $this->error('写入插件数据失败', U('index'));
        }
    }




    /**
     * [uninstall 卸载插件]
     * @return [type] [description]
     */
    public function uninstall()
    {
        $id = trim(I('id'));
        $db_addons = $this->db->find($id);
        $class = get_addon_class($db_addons['name']);
        $this->assign('jumpUrl', U('index'));
        if (!$db_addons || !class_exists($class))
            $this->error('插件不存在', U('index'));
        session('addons_uninstall_error', null);
        $addons = new $class;
        $uninstall_flag = $addons->uninstall();
        if (!$uninstall_flag)
            $this->error('执行插件预卸载操作失败' . session('addons_uninstall_error'), U('index'));
        // 删除数据
        $delete = $this->db->where(array('name'=> $db_addons['name']))->delete();
        if ($delete === false)
        {
            $this->error('卸载插件失败', U('index'));
        }
        else
        {
            $this->success('插件卸载成功！', U('index'));
        }
    }


    /**
     * [DelAddons 删除插件]
     * @param string $plugin_name [description]
     */
    public function DelAddons($plugin_name = '')
    {

        $plugin_path = UNION_ADDON_PATH . $plugin_name . '/';
        if (\Lib\Util\Dir::del($plugin_path))
        {
            $this->success('删除成功');
        }
        else
        {
            $this->error("删除失败");
        }

    }


    /*----------------------------------------属性定义----------------------------------------------*/

    // 验证插件唯一性
    public function PlugsCheck($name, $arr)
    {
        if (is_dir(UNION_ADDON_PATH . $name))
        {
            return true;
        }
        else
        {
            return false;
        }
    }


    /**
     * [enable 启用插件]
     * @return [type] [description]
     */
    public function enable()
    {
        $id     =   I('id');
        $msg    =   array('success'=>'启用成功', 'error'=>'启用失败');
        S('hooks', null);
        $this->resume('Plugs', array('id'=> $id), $msg);
    }

    /**
     * [disable 禁用插件]
     * @return [type] [description]
     */
    public function disable()
    {
        $id     =   I('id');
        $msg    =   array('success'=>'禁用成功', 'error'=>'禁用失败');
        S('hooks', null);
        $this->forbid('Plugs', array('id'=> $id), $msg);
    }



    /**
     * [config 插件配置]
     * @return [type] [description]
     */
    public function config()
    {
        $id = I('id', 0, 'intval');
        $addon = $this->db->where(array('id'=> $id))->find();
        if (!$addon) $this->error('插件未安装');
        $addon_class = get_addon_class($addon['name']);
        if (!class_exists($addon_class))
            trace("插件{$addon['name']}无法实例化,", 'ADDONS', 'ERR');
        $data = new $addon_class;
        $addon['Addon_PATH'] = $data->Addon_PATH;
        $addon['custom_config'] = $data->custom_config;
        $db_config = $addon['config'];
        $addon['config'] = include $data->config_file;
        if ($db_config)
        {
            $db_config = json_decode($db_config, true);
            foreach ($addon['config'] as $key => $value)
            {
                if ($value['type'] != 'group')
                {
                    $addon['config'][$key]['value'] = $db_config[$key];
                }
                else
                {
                    foreach ($value['options'] as $gourp => $options)
                    {
                        foreach ($options['options'] as $gkey => $value)
                        {
                            $addon['config'][$key]['options'][$gourp]['options'][$gkey]['value'] = $db_config[$gkey];
                        }
                    }
                }
            }
        }
        $this->assign('data', $addon);

        $addons_dir = UNION_ADDON_PATH;

        $file = $addons_dir . $addon['name'] . '/' . $data->custom_config;

        if ($addon['custom_config'])
        {
            $custom_configs = $this->fetch($file);
            $this->assign('custom_configs', $custom_configs);
            $this->display('custom_config');

        }
        else
        {
            $this->display();

        }
    }


    /**
     * [adminList 后台面板]
     * @param  [type] $name [description]
     * @return [type]       [description]
     */
    /*public function adminList($name)
    {
        $class = get_addon_class($name);

        if(!class_exists($class))
            $this->error('插件不存在');
        $addon  =   new $class();
        $this->assign('addon', $addon);
        $param  =   $addon->admin_list;
        if(!$param)
            $this->error('插件列表信息不正确');
        $this->meta_title = $addon->info['title'];
        extract($param);
        $this->assign('title', $addon->info['title']);
        $this->assign($param);
        if(!isset($fields))
            $fields = '*';
        if(!isset($map))
            $map = array();
        if(isset($model))
            $list = $this->lists(D("Addons://{$model}/{$model}")->field($fields),$map);
        $this->assign('_list', $list);
        if($addon->custom_adminlist)
            $this->assign('custom_adminlist', $this->fetch($addon->addon_path.$addon->custom_adminlist));
        $this->display();
    }*/

    public function adminList($name)
    {

        if(method_exists(A('Plugs://'.$name.'/Admin') ,'buildList'))
        {
            A('Plugs://'.$name.'/Admin')->buildList();
            exit;
        }

        $class = get_addon_class($name);
        if(!class_exists($class))
            $this->error('插件不存在');
        $addon  =   new $class();
        $this->assign('addon', $addon);
        $param  =   $addon->admin_list;
        if(!$param)
            $this->error('插件列表信息不正确');
        $this->meta_title = $addon->info['title'];
        extract($param);
        $this->assign('title', $addon->info['title']);
        $this->assign($param);
        if(!isset($fields))
            $fields = '*';
        if(!isset($map))
            $map = array();
        if(isset($model))
            $list = $this->lists(D("Plugs://{$model}/{$model}")->field($fields),$map,$order);
        $this->assign('_list', $list);
        if($addon->custom_adminlist)
            $this->assign('custom_adminlist', $this->fetch($addon->addon_path.$addon->custom_adminlist));
        $this->display();
    }


    /**
     * [preview 插件控制器代码]
     * @param  boolean $output [description]
     * @return [type]          [description]
     */
    public function preview($output = true)
    {
        // 获取数据
        $data                   =   $_POST;
        // 插件名首字母大小
        $data['name']           =   ucfirst($data['name']);
        $data['status']         =   (int)$data['status'];
        $extend                 =   array();

        if($data['has_adminlist'] == 1)
        {
            $admin_list = <<<str


        public \$admin_list = array(
            'model'     =>  'Example',      // 要查的表
            'fields'    =>  '*',            // 要查的字段
            'map'       =>  '',             // 查询条件, 如果需要可以再插件类的构造方法里动态重置这个属性
            'order'     =>  'id desc',      // 排序,
            'listKey'   =>  array(
                // 这里定义的是除了id序号外的表格里字段显示的表头名
                '字段名'    => '表头显示名'
            ),
        );
str;
        $extend[] = $admin_list;
    }
        $extend = implode('', $extend);
        $hooks = '';
        foreach ($data['hooks'] as $value)
        {
            $hooks .= <<<str
        // 实现的{$value}钩子方法
        public function {$value}(\$param)
        {
            // 钩子行为方法
        }

str;
        }

        $tpl = <<<str
<?php
/**
 * {$data['title']}插件
 * @author {$data['author']}
 */
namespace Plugs\\{$data['name']};
use Common\Controller\Addon;
class {$data['name']}Addon extends Addon
{
        public \$info = array(
            'name'          =>  '{$data['name']}',
            'title'         =>  '{$data['title']}',
            'description'   =>  '{$data['description']}',
            'status'        =>  {$data['status']},
            'author'        =>  '{$data['author']}',
            'email'         =>  '{$data['email']}',
            'version'       =>  '{$data['version']}'
        );{$extend}

        // 安装
        public function install()
        {
            return true;
        }

        // 卸载
        public function uninstall()
        {
            return true;
        }

{$hooks}
}
str;
        if($output)
            exit($tpl);
        else
            return $tpl;
    }



    /**
     * [pluginExportHandle 导出插件]
     * @param  string $plugin_name [description]
     * @return [type]              [description]
     */
    public function pluginExportHandle($plugin_name = '',$version = '')
    {
        $plugin_path = 'Plugs/' . $plugin_name . '/';
        $temp_path = RUNTIME_PATH . 'Cache/';

        \Lib\Util\Dir::del(RUNTIME_PATH . 'Cache/');
        \Lib\Util\File::mkDir(RUNTIME_PATH . 'Cache/');

        $file_path = $temp_path . "\\" . $plugin_name . '-' . $version . '.zip';

        $zip = new \ZipArchive; //新建一个ZipArchive的对象
        $res = $zip->open($file_path, \ZipArchive::CREATE);

        if ($res == true)
        {
            \Lib\Util\PHPZip::folderToZip($plugin_path, $zip);
            $zip->close();
        }

        if (!\Lib\Util\File::file_exists($file_path))
        {
            $this->error("该文件不存在，可能是被删除");
        }

        $filename = basename($file_path);
        header("Content-type: application/octet-stream");
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header("Content-Length: " . filesize($file_path));
        readfile($file_path);
    }
}
